#ifndef __PROTOCOL_H__
#define __PROTOCOL_H__

#include <stdint.h>
#include "maze.h"

/** Main Packet **/
#define CTF_HEADER_LENGTH 12
typedef struct CtfHeaderStruct {
	uint16_t sender;
	uint16_t msgType;
	int gameState;
	int bodyLength;
} CtfHeader;

typedef struct CtfPacketStruct {
	CtfHeader header;
	char *body;
} CtfPacket;

/** Map Body **/
#define MAP_HEADER_LENGTH 12
typedef struct MapHeaderStruct {
	uint16_t rows;
	uint16_t cols;
	uint16_t numHome1;
	uint16_t numHome2;
	uint16_t numJail1;
	uint16_t numJail2;
} MapHeader;

typedef struct MapPacketStruct {
	MapHeader header;
	char *map;
} MapPacket;

/** Response Body **/
#define CONNECT_BODY_LENGTH 2
typedef struct ConnectBodyStruct {
	uint16_t playerId;
} ConnectBody;

#define MOVE_BODY_LENGTH 4
typedef struct MoveBodyStruct {
	Position pos;
} MoveBody;

#define PICKUP_BODY_LENGTH 2
typedef struct PickupBodyStruct {
	uint16_t objectId;
} PickupBody;

#define DROP_BODY_LENGTH 6
typedef struct DropBodyStruct {
	uint16_t objectId;
	Position pos;
} DropBody;

#define BLAST_BODY_LENGTH 4
typedef struct BlastBodyStruct {
	Position pos;
} BlastBody;

#define DISCONNECT_BODY_LENGTH 2
typedef struct DisconnectBodyStruct {
	uint16_t result;
} DisconnectBody;


/** Cell + Player Position Update **/
#define CELL_UPDATE_HEADER_LENGTH 4
typedef struct CellUpdateHeaderStruct {
	uint64_t numCellUpdates;
} CellUpdateHeader;

#define CELL_UPDATE_BODY_LENGTH 10
typedef struct CellUpdateBodyStruct {
	Position pos;
	uint16_t cellType;
	uint16_t occupiedByPlayer;
	uint16_t occupiedByObject;
} CellUpdateBody;

typedef struct CellUpdatePacketStruct {
	CellUpdateHeader header;
	CellUpdateBody *updates;
} CellUpdatePacket;


/** Player Update **/
#define PLAYER_UPDATE_HEADER_LENGTH 2
typedef struct PlayerUpdateHeaderStruct {
	uint16_t numPlayerUpdates;
} PlayerUpdateHeader;

#define PLAYER_UPDATE_BODY_LENGTH 6
typedef struct PlayerUpdateBodyStruct {
	uint16_t playerId;
	uint16_t field;
	uint16_t value;
} PlayerUpdateBody;

typedef struct PlayerUpdatePacketStruct {
	PlayerUpdateHeader header;
	PlayerUpdateBody *updates;
} PlayerUpdatePacket;

/** Game Update **/
#define GAME_UPDATE_BODY_LENGTH 2
typedef struct {
	uint16_t gameState;
} GameUpdateBody;

struct PlayerStruct;
/** protocol.c Function Declarations **/
void receive( int sockfd, int port, Maze *m, struct PlayerStruct *myPlayerPtr );
void sendConnectResponse(int sockfd, Maze *m, struct PlayerStruct *myPlayer );
void sendMoveResponse(int sockfd, Maze *m, Position p, struct PlayerStruct *myPlayerPtr);
void sendPickupResponse(int sockfd, Maze *m);
void sendDropResponse(int sockfd, Maze *m);
void sendBlastResponse(int sockfd, Maze *m);
void sendDisconnectResponse(int sockfd, Maze *m);

#endif
